<?php

class Wsdl
{
    // На случай, если что-то не получится: текст сообщения с ошибкой:
    private $errorMessage;

    // WSDL
    private $WSDL;

    // Экземпляр класса SoapClient
    protected $soap;

    /*
     * Ожидаемый ответ от сервера (если нужен):
     * 1. Если это массив (каждый эимент которого - имя метода или свойства объекта, возвращаемого службой),
     *      то последовательно будут вызваны все методы и свойства объекта, заданные в массиве
     *      и возаращён полученный результат;
     * 2. Если это пустое значение (NULL, или параметр вообще не указан) или FALSE
     *      - то класс вернёт объект, полученный от службы;
     * 3. Если это TRUE (или любое непустое значение, отличное от массива) - класс вызовет свойство/метод с именем,
     *      составленным в виде "имя метода"."Result" (именно такой формат имеют по умочанию свойства объектов,
     *      возарщаемых службой, в которых записаны результаты выпоненных действий), т. е., обычно, просто вернёт
     *      результат выполнения метода вызванного в приложении (что-то вроде $WSDL->имя_метода;).
     */
    protected $request;

    /*
     * Параметры, если такие нужны серверу:
     * Это ассоциативный массив: "имя передаваемой серверу переменной"=>"Значение".
     */
    protected $params;

    // Параметры, которые могут передаваться классу SoapClient.
    protected $soapParams;

    // Задаём значения свойствам объекта, соответственно переданным параметрам.
    public function __construct($wsdl, $params=false, $request=false)
    {
        $this->params=$params;
        $this->request=$request;
        $this->WSDL=$wsdl;

        try{
            $this->soap=$this->soapParams ? new SoapClient($wsdl, $this->soapParams) : new SoapClient($wsdl);
            $this->errorMessage=false;
        }catch(SoapFault $error){
            $this->errorMessage=$error->faultstring;
        }
    }

    // Здесь $name - это имя метода или свойства, вызываемого в приложении (что-то вроде $WSDL->$name;)
    public function __get($name)
    {
        // Может быть, это наш собственный метод?
        if(method_exists($this, $name)){
            return $this->$name();
        }
        // Или это наше свойство?
        if(property_exists($this, $name)){
            return $this->$name;
        }
        // Нет? Значит, проверим, не было ли ошибок при создании экземпляра SoapClient.
        if($this->errorMessage){
            return false;
        }

        // Ну, и если все предыдущие условия не выполнены, попробуем вызвать метод web-службы...
        try{
            $result=$this->params ? $this->soap->$name($this->params) : $this->soap->$name();
            if($this->request){
                if(is_array($this->request)){
                    foreach($this->request as $obj){
                        if(property_exists($result, $obj) || method_exists($result, $obj))
                            $result=$result->$obj;
                    }
                }else{
                    $param=$name.'Result';
                    $result=$result->$param;
                }
            }
        }catch(SoapFault $error){
            $this->errorMessage=$error->faultstring;
            return false;
        }

        return $result;
    }

    // Установим значение свойства, если такое есть.
    public function __set($name, $value)
    {
        if(property_exists($this, $name)){
            $this->$name=$value;
        }else{
            $this->errorMessage='Класс  WSDL не имеет свойства "'.$name.'", обратитесь к документации, чтобы проверить правильность написания имени свойства';
        }
    }
}